﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MiniFox.Infrastructure;
using MiniFox.Platform.Exceptions;
using MiniFox.Platform.OAuth2.Configurations;
using MiniFox.Platform.OAuth2.Models;
using MiniFox.Platform.OAuth2.Web.Filters;
using MiniFox.Platform.Resources;
using MiniFox.Platform.Web.Filters;
using MiniFox.Resources;
using MiniFox.Web.Filters;
using MiniFox.Web.Infrastructure;
using System.ComponentModel.DataAnnotations;

namespace MiniFox.Platform.OAuth2.Web
{
    /// <summary>
    /// 
    /// </summary>
    [AllowAnonymous, NoCache, PassportFilter, ValidationFilter]
    public class PassportController : OAuth2ControllerBase<IPassportService>
    {
        #region 登录

        /// <summary>
        /// 
        /// </summary>
        /// <param name="authTicket"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult SignIn([FromQuery(Name = OpenAuthKey.AUTH_TICKET)] string authTicket)
        {
            string gotoUrl = Via(this.Component.Configuration.SignInViaName);
            if (!string.IsNullOrEmpty(gotoUrl)) //ua匹配成功后，走其它登录通道(微信、钉钉等)
            {
                return this.Redirect(gotoUrl);
            }
            //ua未匹配到，直接走账密登录页面
            return ResponseResult(new Response<PassportConfiguration>(this.Component.Configuration));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="authTicket"></param>
        /// <param name="signIn"></param>
        /// <returns></returns>
        [HttpPost, Verify]
        public RedirectResponse SignIn([FromQuery(Name = OpenAuthKey.AUTH_TICKET), Required(ErrorMessageResourceType = typeof(CommonMessages), ErrorMessageResourceName = "MSG_CommonRequired")] string authTicket, [FromBody]PasswordSignIn signIn)
        {
            RedirectResponse response = new();
            if (this.Component.SignIn(authTicket, signIn))
            {
                string redirectUri = this.Component.CreateAuthUri(authTicket);
                response.RedirectUri = string.IsNullOrEmpty(redirectUri) ? "/" : redirectUri;
            }
            else
            {
                response.Code = ResErrorCode.ERR_SignInUnMatch;
                response.Message = ResMessage.ERR_SignInUnMatch;
            }
            return response;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="authTicket"></param>
        /// <param name="signIn"></param>
        /// <returns></returns>
        [HttpPost, Verify]
        public virtual RedirectResponse PinCodeSignIn([FromQuery(Name = OpenAuthKey.AUTH_TICKET), Required(ErrorMessageResourceType = typeof(CommonMessages), ErrorMessageResourceName = "MSG_CommonRequired")] string authTicket, [FromBody] PinCodeSignIn signIn)
        {
            RedirectResponse response = new();
            if (this.Component.SignIn(authTicket, signIn))
            {
                string redirectUri = this.Component.CreateAuthUri(authTicket);
                response.RedirectUri = redirectUri;
            }
            else
            {
                response.Code = ResErrorCode.ERR_SignInUnMatch;
                response.Message = ResMessage.ERR_SignInUnMatch;
            }
            return response;
        }

        #region 扫码登录

        /// <summary>
        /// 轮询接口，通过授权票据获得身份
        /// </summary>
        /// <param name="authTicket"></param>
        /// <returns></returns>
        [HttpGet]
        public virtual RedirectResponse<AuthorizeResult> ScanSignin([FromQuery(Name = OpenAuthKey.AUTH_TICKET), Required(ErrorMessageResourceType = typeof(CommonMessages), ErrorMessageResourceName = "MSG_CommonRequired")] string authTicket)
        {
            RedirectResponse<AuthorizeResult> response;
            string redirectUri = string.Empty;
            try
            {
                var result = this.Component.SignIn(authTicket);
                switch (result.Status)
                {
                    case DeviceAuthorizeStatus.Verified:
                        break;
                    case DeviceAuthorizeStatus.Authorized:
                        //回跳授权地址
                        redirectUri = this.Component.CreateAuthUri(authTicket);
                        break;
                    default:
                        break;
                }
                response = new RedirectResponse<AuthorizeResult>(result)
                {
                    RedirectUri = redirectUri
                };

            }
            catch (UnregisteredException e)
            {
                redirectUri = this.Url.Action(nameof(Bind), new { auth_ticket = authTicket });
                response = new RedirectResponse<AuthorizeResult>(new AuthorizeResult(authTicket)
                {
                    OpenAuthUser = e.AuthUser,
                    Status = DeviceAuthorizeStatus.Authorized
                })
                {
                    RedirectUri = redirectUri
                };
            }
            catch (Exception e) 
            {
                throw e.InnerException ?? e;
            }
            return response;
        }

        #endregion

        #endregion

        #region 注册
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult Register([FromQuery(Name = OpenAuthKey.AUTH_TICKET), Required(ErrorMessageResourceType = typeof(CommonMessages), ErrorMessageResourceName = "MSG_CommonRequired")] string authTicket)
        {
            if (!this.Component.Configuration.EnableRegister)
            {
                throw new PlatformException("ERR_DisableRegAccount");
            }
            return ResponseResult(new Response<PassportConfiguration>(this.Component.Configuration));
        }

        /// <summary>
        /// 完整注册
        /// </summary>
        /// <param name="authTicket"></param>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost, Verify]
        public virtual RedirectResponse Register([FromQuery(Name = OpenAuthKey.AUTH_TICKET), Required(ErrorMessageResourceType = typeof(CommonMessages), ErrorMessageResourceName = "MSG_CommonRequired")] string authTicket,
             [FromBody] Register model)
        {
            RedirectResponse response = new();
            if (this.Component.Register(authTicket, model))
            {
                response.Message = ResMessage.MSG_RegAccountForActive;
            }
            else
            {
                response.Code = ResErrorCode.ERR_RegAccountFail;
                response.Message = ResMessage.ERR_RegAccountFail;
            }
            return response;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="authTicket"></param>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost, Verify]
        public virtual RedirectResponse RegLoginName([FromQuery(Name = OpenAuthKey.AUTH_TICKET), Required(ErrorMessageResourceType = typeof(CommonMessages), ErrorMessageResourceName = "MSG_CommonRequired")] string authTicket,
             [FromBody] RegisterLoginName model)
        {
            RedirectResponse response = new();
            if (this.Component.Register(authTicket, model.LoginName, model.Password))
            {
                response.Message = ResMessage.MSG_RegAccountSuccessful;
            }
            else
            {
                response.Code = ResErrorCode.ERR_RegAccountFail;
                response.Message = ResMessage.ERR_RegAccountFail;
            }
            return response;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="authTicket"></param>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost, Verify]
        public virtual RedirectResponse RegEmail([FromQuery(Name = OpenAuthKey.AUTH_TICKET), Required(ErrorMessageResourceType = typeof(CommonMessages), ErrorMessageResourceName = "MSG_CommonRequired")] string authTicket,
            [FromBody] RegisterEmail model)
        {

            RedirectResponse response = new();
            if (this.Component.Register(authTicket, model.SecEmail, model.Password))
            {
                response.Message = ResMessage.MSG_RegAccountSuccessful;

            }
            else
            {
                response.Code = ResErrorCode.ERR_RegAccountFail;
                response.Message = ResMessage.ERR_RegAccountFail;
            }
            return response;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="authTicket"></param>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        public virtual RedirectResponse Reg([FromQuery(Name = OpenAuthKey.AUTH_TICKET), Required(ErrorMessageResourceType = typeof(CommonMessages), ErrorMessageResourceName = "MSG_CommonRequired")] string authTicket,
            [FromBody] PinCodeSignIn model)
        {
            RedirectResponse response = new();
            if (this.Component.Register(authTicket, model))
            {
                response.Message = ResMessage.MSG_RegAccountSuccessful;

            }
            else
            {
                response.Code = ResErrorCode.ERR_RegAccountFail;
                response.Message = ResMessage.ERR_RegAccountFail;
            }
            return response;
        }

        /// <summary>
        /// 帐户激活
        /// </summary>
        /// <param name="ticket"></param>
        /// <returns></returns>
        [HttpGet]
        public RedirectResponse AccountActivate([FromQuery(Name = "ticket"), Required(ErrorMessageResourceType = typeof(CommonMessages), ErrorMessageResourceName = "MSG_CommonRequired")] string ticket)
        {
            RedirectResponse response = new();
            if (this.Component.ActivateIdentity(ticket))
            {
                response.RedirectUri = Url.Action("entry", new { name = "info", ResourceName = "MSG_ActiveAccountSuccessful" });
            }
            else
            {
                throw new PlatformException("ERR_InvalidTicket");
            }

            return response;
        }

        #endregion

        #region 密码找回
        /// <summary>
        /// 
        /// </summary>
        /// <param name="retakePassword"></param>
        /// <returns></returns>
        [HttpPost]
        public Response IssueTicket([FromBody] RetakePassword retakePassword)
        {
            Response response = new();
            if (this.Component.IssueTicket(retakePassword.SignName, retakePassword.RetakeMode))
            {
                response.Message = ResMessage.MSG_ChangePwdSuccessful;
            }
            else
            {
                response.Code = ResErrorCode.ERR_ResetPwdFail;
                response.Message = ResMessage.ERR_ResetPwdFail;
            }
            return response;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="resetPassword"></param>
        /// <returns></returns>
        [HttpPost]
        public Response ResetPassword([FromBody] ResetPassword resetPassword)
        {
            Response response = new();
            if (this.Component.ResetPassword(resetPassword.Ticket, resetPassword.NewPassword))
            {
                response.Message = ResMessage.MSG_ChangePwdSuccessful;
            }
            else
            {
                response.Code = ResErrorCode.ERR_ResetPwdFail;
                response.Message = ResMessage.ERR_ResetPwdFail;
            }
            return response;
        }
        #endregion
        /// <summary>
        /// 绑定页
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult Bind([FromQuery(Name = OpenAuthKey.AUTH_TICKET), Required(ErrorMessageResourceType = typeof(CommonMessages), ErrorMessageResourceName = "MSG_CommonRequired")] string authTicket)
        {
            return ResponseResult(new Response<PassportConfiguration>(this.Component.Configuration));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="authTicket"></param>
        /// <param name="signIn"></param>
        /// <returns></returns>
        [HttpPost, Verify]
        public IActionResult Bind([FromQuery(Name = OpenAuthKey.AUTH_TICKET), Required(ErrorMessageResourceType = typeof(CommonMessages), ErrorMessageResourceName = "MSG_CommonRequired")] string authTicket, [FromBody] PasswordSignIn signIn)
        {
            RedirectResponse response = new();
            if (this.Component.SignIn(authTicket, signIn))
            {
                this.Component.BindIdentity(authTicket);
                string redirectUri = this.Component.CreateAuthUri(authTicket);
                response.RedirectUri = string.IsNullOrEmpty(redirectUri) ? "/" : redirectUri;
            }
            else
            {
                response.Code = ResErrorCode.ERR_SignInUnMatch;
                response.Message = ResMessage.ERR_SignInUnMatch;
            }
            return this.ResponseResult(response);
        }
    }
}
